package com.webanovare.model;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 * 
 * @author daniel based on hajo's AbstractDAO
 */
public abstract class AbstractDAO<T, K> implements IDAO<T, K> {

    @PersistenceContext
    private EntityManager em;
    
    private Class<T> clazz;

    public AbstractDAO() {
    }
    
    protected AbstractDAO(Class<T> clazz) {
        this.clazz = clazz;
    }
    
    @Override
    public T add(T t) {
        System.out.println("adding: " + t);
        em.persist(t);
        
        return null;
    }

    @Override
    public void remove(T t) {
        em.remove(t);
    }
    
    @Override
    public void removeWithId(K id) {
        T obj = em.find(clazz, id);
        em.remove(obj);
    }

    @Override
    public void update(T t) {
        System.out.println("Vill uppdatera nyhet. Är i abstractDAO");
        em.merge(t);
    }

    @Override
    public T find(K id) {
        T obj = null;
        EntityManager em = null;
        try {
            obj = em.find(clazz, id);
        } catch(Exception ex) {
            ex.printStackTrace();
            em.getTransaction().rollback();
        } finally {
            if(em != null) {
                em.close();
            }
        }
        return obj;
    }
    

    @Override
    public List<T> getAll() {
        List<T> result = new ArrayList<>();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(clazz));
            Query q = em.createQuery(cq);
            result.addAll(q.getResultList());
        } catch (Exception ex) {
            ex.printStackTrace();
        } 
        
        return result;
    }

    @Override
    public List<T> getAllOrderBy(String column, boolean asc) {
        List<T> result = new ArrayList<>();
        try {
            CriteriaBuilder cb = em.getCriteriaBuilder();
            CriteriaQuery<T> q = cb.createQuery(clazz);
            Root<T> c = q.from(clazz);
            q.select(c);
            if (asc) {
                q.orderBy(cb.asc(c.get(column)));
            }
            else {
                q.orderBy(cb.desc(c.get(column)));
            }
            
            Query res = em.createQuery(q);
            result.addAll(res.getResultList());
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            em.close();
        }
        
        return result;
    }
    
    @Override
    public int getCount() {
        return getAll().size();
    }
    
    protected void setEntitymanager(EntityManager em) {
        System.out.println("entity manager satt" + em + " " + this.clazz);
        this.em = em;
    }
}
